package l1j.opqlo.List;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.Config;
import l1j.server.echo.ClientThread;
import l1j.server.server.datatables.lock.AccountReading;
import l1j.server.server.templates.L1Account;

/**
 * 連線用戶管理
 *
 * @author dexc
 *
 */
public class OnlineUser {

	private static final Logger _log = Logger.getLogger(OnlineUser.class
			.getName());
	private static OnlineUser _instance;

	public static OnlineUser get() {
		if (_instance == null) {
			_instance = new OnlineUser();
		}

		return _instance;
	}

	// Map<K,V>
	private final Map<String, ClientThread> _clientList;

	private Collection<String> _allValues;

	private Collection<ClientThread> _allClient;

	private OnlineUser() {
		this._clientList = new ConcurrentHashMap<String, ClientThread>();
	}

	/**
	 * 增加連線用戶資料
	 *
	 * @param value
	 *            帳號
	 * @param client
	 *            連線線程
	 * @return
	 */
	public boolean addClient(final L1Account value, final ClientThread client) {
		final String accountName = value.get_login();
		final ClientThread xclient = this._clientList.get(accountName);
		if (xclient == null) {
			// 線程 帳戶 交叉設置
			client.setAccount(value);
			value.set_isLoad(true);
			AccountReading.get().updateLan(accountName, true);
			this._clientList.put(accountName, client);
			_log.info("帳號登入: " + value.get_login() + " 目前連線帳號: "
					+ this._clientList.size());

			return true;

		} else {
			xclient.close();
			client.close();
			_log.log(Level.SEVERE, "連線列表中重複資料: " + value.get_login() + "\n");
			return false;
		}
	}

	/**
	 * 全部連線用戶(Collection)
	 *
	 * @return
	 */
	public Collection<ClientThread> all() {
		try {
			final Collection<ClientThread> vs = this._allClient;
			return vs != null ? vs : (this._allClient = Collections
					.unmodifiableCollection(this._clientList.values()));

		} catch (final Exception e) {
			// _log.error(e.getLocalizedMessage(), e);
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
		return null;
	}

	/**
	 * 取回連線用戶 ClientThread 資料
	 *
	 * @param accountName
	 * @return 該帳戶未連線 傳回NULL
	 */
	public ClientThread get(final String accountName) {
		final ClientThread client = this._clientList.get(accountName);
		return client;
	}

	/**
	 * 傳回全部連線中帳戶
	 *
	 * @return
	 */
	public Collection<String> getObject() {
		final Collection<String> vs = this._allValues;
		return vs != null ? vs : (this._allValues = Collections
				.unmodifiableCollection(this._clientList.keySet()));
	}

	/**
	 * 用戶連線中
	 *
	 * @param accountName
	 * @return
	 */
	public boolean isLan(final String accountName) {
		final ClientThread client = this._clientList.get(accountName);
		if (client != null) {
			return true;
		}
		return false;
	}

	/**
	 * 是否已達最大連線數量
	 *
	 * @return
	 */
	public boolean isMax() {
		if (this._clientList.size() >= Config.MAX_ONLINE_USERS) {
			return true;
		}
		return false;
	}

	/**
	 * 中斷全部用戶
	 *
	 * @return
	 */
	public void kickAll() {
		for (final String acc : this._clientList.keySet()) {
			this.remove(acc);
		}
	}

	/**
	 * 全部連線用戶(Map)
	 *
	 * @return
	 */
	public Map<String, ClientThread> map() {
		return this._clientList;
	}

	/**
	 * 移除連線用戶資料
	 *
	 * @param accountName
	 */
	public void remove(final String accountName) {
		final ClientThread xclient = this._clientList.get(accountName);
		if (xclient != null) {
			final L1Account value = xclient.getAccount();
			value.set_isLoad(false);
			AccountReading.get().updateLan(accountName, false);
			this._clientList.remove(accountName);
		}
	}

	/**
	 * 連線數量
	 *
	 * @return
	 */
	public int size() {
		return this._clientList.size();
	}
}
